package com.runjian.rundo.iot.agent.common.network.tcp.config;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.runjian.rundo.iot.agent.business.publisher.DeviceMessagePublisher;
import com.runjian.rundo.iot.agent.common.codec.DeviceMessageCodec;
import com.runjian.rundo.iot.agent.common.network.tcp.handle.TcpIdleEventHandler;
import com.runjian.rundo.iot.agent.common.network.tcp.handle.TcpMessageHandler;
import com.runjian.rundo.iot.agent.common.network.tcp.parser.*;
import com.runjian.rundo.iot.agent.common.network.tcp.session.DefaultTcpDeviceSessionManager;
import com.runjian.rundo.iot.agent.common.network.tcp.session.TcpDeviceSessionManager;

import io.netty.handler.codec.ByteToMessageDecoder;
import org.springframework.core.annotation.Order;

/**
 * tcp透传网络组件自动化配置
 *
 * @author CaoQingHua
 */
@EnableConfigurationProperties(TcpNetworkProperties.class)
@Configuration
@Order(2)
public class TcpAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(TcpDeviceSessionManager.class)
    public DefaultTcpDeviceSessionManager defaultTcpDeviceSessionManager() {
        return new DefaultTcpDeviceSessionManager();
    }

    @Bean
    @ConditionalOnMissingBean(TcpMessageHandler.class)
    public TcpMessageHandler tcpMessageHandler(TcpDeviceSessionManager sessionManager, DeviceMessageCodec codec,
        DeviceMessagePublisher deviceMessagePublisher) {
        return new TcpMessageHandler(sessionManager, codec, deviceMessagePublisher);
    }

    @Bean
    @ConditionalOnMissingBean(TcpIdleEventHandler.class)
    public TcpIdleEventHandler tcpIdleEventHandler(TcpDeviceSessionManager sessionManager, DeviceMessageCodec codec) {
        return new TcpIdleEventHandler(sessionManager, codec);
    }

    @Bean
    @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "direct", matchIfMissing = true)
    public PayloadParser directPayloadParser() {
        return new DirectPayloadParser();
    }

    @Bean
    @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "fixed")
    public PayloadParser fixedPayloadParser(TcpNetworkProperties tcpNetworkProperties) {
        return new FixedLengthPayloadParser(tcpNetworkProperties);
    }

    @Bean
    @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "delimiter")
    public PayloadParser delimiterPayloadParser(TcpNetworkProperties tcpNetworkProperties) {
        return new DelimitedPayloadParser(tcpNetworkProperties);
    }

    @Bean
    @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "custom")
    public PayloadParser customPayloadParser(ByteToMessageDecoder byteToMessageDecoder) {
        return new CustomPayloadParser(byteToMessageDecoder.getClass());
    }

    @Bean
    @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "lengthField")
    public PayloadParser lengthFieldPayloadParser(TcpNetworkProperties tcpNetworkProperties) {
        return new LengthBasedPayloadParser(tcpNetworkProperties);
    }

    // @Bean
    // @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "direct", matchIfMissing = true)
    // public PayloadParser directPayloadParser() {
    // return new DirectPayloadParser();
    // }
    //
    // @Bean
    // @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "fixed")
    // public PayloadParser fixedPayloadParser(TcpNetworkProperties tcpNetworkProperties) {
    // return new FixedLengthPayloadParser(tcpNetworkProperties);
    // }
    //
    // @Bean
    // @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "delimiter")
    // public PayloadParser delimiterPayloadParser(TcpNetworkProperties tcpNetworkProperties) {
    // return new DelimitedPayloadParser(tcpNetworkProperties);
    // }
    //
    // @Bean
    // @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "custom")
    // public PayloadParser customPayloadParser(ByteToMessageDecoder byteToMessageDecoder) {
    // return new CustomPayloadParser(byteToMessageDecoder.getClass());
    // }
    //
    // @Bean
    // @ConditionalOnProperty(value = "network.tcp.payloadParserType", havingValue = "lengthField")
    // public PayloadParser lengthFieldPayloadParser(TcpNetworkProperties tcpNetworkProperties) {
    // return new LengthBasedPayloadParser(tcpNetworkProperties);
    // }

    // @Bean
    // public NetworkServer networkServer(NetworkProperties baseNetworkProperties, TcpNetworkProperties
    // tcpNetworkProperties) {
    // return new TcpNetworkServer(baseNetworkProperties, tcpNetworkProperties);
    // }
}
